package dragon.verification;

import dragon.security.SecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.filter.OncePerRequestFilter;
import org.apache.commons.lang3.StringUtils;

import org.springframework.security.core.AuthenticationException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @Author: Leo
 * @Date: 2020/2/20 12:02
 * 验证码过滤器，继承OncePerRequestFilter，确保每次request只做一次过滤
 */
@WebFilter
public class VerificationCodeFilter extends OncePerRequestFilter {

    private AuthenticationFailureHandler authenticationFailureHandler;

    /**
     * Same contract as for {@code doFilter}, but guaranteed to be
     * just invoked once per request within a single request thread.
     * See {@link #shouldNotFilterAsyncDispatch()} for details.
     * <p>Provides HttpServletRequest and HttpServletResponse arguments instead of the
     * default ServletRequest and ServletResponse ones.
     *
     * @param request
     * @param response
     * @param filterChain
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //request的路径是登录路径，并且方法是post才进行过滤处理
        if(StringUtils.equals(Constants.FILTER_URL,request.getRequestURI()) &&
         StringUtils.equalsIgnoreCase(request.getMethod(),"post")){
            //提取request的验证码（用户填写）
            String code = request.getParameter(Constants.VERIFICATION_CODE);
            //提取session的验证码（系统生成发给用户）
            HttpSession session = request.getSession();
            Object attribute = session.getAttribute(Constants.VERIFICATION_CODE);
            VerificationCode codeEntity = null;
            if(attribute != null){
                codeEntity = (VerificationCode)attribute;
            }
            try {
                //对比过滤
                checkCode(code, codeEntity);
            }catch (AuthenticationException ex){
                authenticationFailureHandler.onAuthenticationFailure(request,response,ex);
                return;
            }
        }
        //继续做后面的过滤
        filterChain.doFilter(request,response);
    }

    /**
     * 检查验证码
     * @param code
     * @param codeEntity
     * @return
     * @throws AuthenticationException
     */
    private boolean checkCode(String code , VerificationCode codeEntity) throws AuthenticationException {
        if(codeEntity == null){
            throw new VerificationException("此session没有验证码，请重新刷新页面");
        }

        if(codeEntity.isExpired()){
            throw new VerificationException("验证码已过期");
        }

        if(!StringUtils.endsWithIgnoreCase(code,codeEntity.getCode())){
            throw new VerificationException("验证码错误");
        }

        return true;
    }

    public void setAuthenticationFailureHandler(AuthenticationFailureHandler handler){
        this.authenticationFailureHandler = handler;
    }
}
